package CrowdCounting.Model.CrowdCounting;

import Const.State;
import CrowdCounting.Model.AbstractComponentFactory;
import CrowdCounting.Model.ComponentFactoryImp.ComponentFactory;
import CrowdCounting.Model.Util;
import CrowdCounting.RunnableTask.CrowdCountingTask.CCShowLabelTaskImp.CCShowImageLabelTaskProxy;
import CrowdCounting.RunnableTask.CrowdCountingTask.CCShowLabelTaskImp.CCShowTextLabelTask;
import CrowdCounting.RunnableTask.PythonRunTask;
import CrowdCounting.RunnableTask.ShowLabelTask;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Properties;
import java.util.logging.Level;

import static Const.State.*;

public class CrowdCountingShow {

    private CrowdCountingDisplayFrame crowdCountingDisplayFrame;
    private JPanel contentPane;
    private JLabel warningImageLabel;
    private JLabel crowdImageLabel;
    private JLabel personNumTextLabel;
    private JLabel optErrorTextLabel;

    private static volatile State showLabelThreadState = CLOSE;

    private ShowLabelTask showWarningImageTask;
    private ShowLabelTask showCrowdImageTask;
    private PythonRunTask pythonScriptTask;
    private ShowLabelTask showPersonNumTask;

    private static final String END_FLAG_FILE = "python_end_flag.txt";
    private static final String STOP_FLAG_FILE = "python_stop_flag.txt";

    private JTextField segmentTextInput;
    private boolean segmentTextInputFlag = false;
    private JTextField thresholdTextInput;
    private boolean thresholdTextInputFlag = false;

    private AbstractComponentFactory componentFactory;


    public CrowdCountingShow(String crowdImagePathRoot, String warningImagePathRoot, int width, int height) {
        if ((!new File(warningImagePathRoot).exists()) || (!new File(crowdImagePathRoot).exists())) {
            throw new RuntimeException("路径不存在：" + warningImagePathRoot + "; " + crowdImagePathRoot);
        }

        componentFactory = new ComponentFactory();

        crowdCountingDisplayFrame = new CrowdCountingDisplayFrame("人群密度异常预警系统", width, height);
        contentPane = (JPanel) crowdCountingDisplayFrame.getContentPane();
        contentPane.setLayout(null);
        warningImageLabel = new JLabel();
        crowdImageLabel = new JLabel();
        personNumTextLabel = new JLabel("当前预测人数：--");

        Properties properties = Util.loadProperties("config.properties");

        pythonScriptTask = new PythonRunTask(properties.getProperty("pythonInterpreter"), properties.getProperty("pythonScriptPath"), true);
        showWarningImageTask = new CCShowImageLabelTaskProxy(crowdCountingDisplayFrame, warningImageLabel, warningImagePathRoot);
        showCrowdImageTask = new CCShowImageLabelTaskProxy(crowdCountingDisplayFrame, crowdImageLabel, crowdImagePathRoot);
        showPersonNumTask = new CCShowTextLabelTask(crowdCountingDisplayFrame, personNumTextLabel, pythonScriptTask);
    }

    public static State getShowLabelThreadState() {
        return showLabelThreadState;
    }

    public static void setShowLabelThreadState(State showImageState) {
        showLabelThreadState = showImageState;
    }

    public void start() {
        showLabelThreadState = START;
        while (pythonScriptTask != null && pythonScriptTask.isAlive()) {
            Util.sleepTime(1000);
            pythonScriptTask.endPythonScript();
        }
        new Thread(pythonScriptTask, "pythonScriptTask").start();
        Util.sleepTime(1000);

        new Thread(showWarningImageTask, "showWarningImage").start();
        new Thread(showCrowdImageTask, "showCrowdImage").start();
        new Thread(showPersonNumTask, "showPersonNum").start();
    }

    public void addFrameComponents(){

        JButton startButton = (JButton) componentFactory.getComponent(new JButton("Start"), 100, 50, 50, 25, Color.BLUE, 25);
        JButton stopButton = (JButton) componentFactory.getComponent(new JButton("Stop"), 100, 50, 150, 25, Color.MAGENTA, 25);
        JButton closeButton = (JButton) componentFactory.getComponent(new JButton("End"), 100, 50, 250, 25, Color.RED, 25);

        segmentTextInput = (JTextField) componentFactory.getComponent(new JTextField(), 80, 25, 140, 110, Color.BLACK, 20);
        segmentTextInput.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2, true));
        JLabel segmentTextInputLabel = (JLabel) componentFactory.getComponent(new JLabel("分块尺度"), 100, 25, 45, 110, Color.BLACK, 20);

        thresholdTextInput = (JTextField) componentFactory.getComponent(new JTextField(), 80, 25, 140, 140, Color.BLACK, 20);
        thresholdTextInput.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2, true));
        JLabel thresholdTextInputLabel = (JLabel) componentFactory.getComponent(new JLabel("子块阈值"), 100, 25, 45, 140, Color.BLACK, 20);


        JPanel warningImagePanel = componentFactory.getPaneDefault(500, 500, 650, 200);
        warningImageLabel = (JLabel) componentFactory.getComponent(warningImageLabel, 500, 500, 60, 20, null, 0);
        JLabel warningImageTextLabel = (JLabel) componentFactory.getComponent(new JLabel("预警图像"), 200, 30, 190, 20, Color.BLACK, 30);

        warningImagePanel.add(warningImageLabel);
        warningImagePanel.add(warningImageTextLabel);

        JPanel crowdImagePanel = componentFactory.getPaneDefault(500, 500, 50, 200);
        crowdImageLabel = (JLabel) componentFactory.getComponent(crowdImageLabel, 500, 500, 60, 20, null, 0);
        JLabel crowdImageTextLabel = (JLabel) componentFactory.getComponent(new JLabel("人群图像"), 200, 30, 190, 20, Color.BLACK, 30);

        crowdImagePanel.add(crowdImageLabel);
        crowdImagePanel.add(crowdImageTextLabel);


        personNumTextLabel = (JLabel) componentFactory.getComponent(personNumTextLabel, 300, 100, 500, 80, Color.BLACK, 35);
        optErrorTextLabel = (JLabel) componentFactory.getComponent(new JLabel(), 1000, 100, 500, 15, Color.RED, 40);

        startButton.addActionListener(e -> {
            startAction();
        });

        closeButton.addActionListener(e -> {
            closeAction();
        });

        stopButton.addActionListener(e -> {
            stopAction();
        });

        segmentTextInput.addActionListener(e -> {
            segmentTextInputAction();
        });

        thresholdTextInput.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                thresholdTextInputAction();
            }
        });


        contentPane.add(startButton);
        contentPane.add(closeButton);
        contentPane.add(stopButton);
        contentPane.add(warningImagePanel);
        contentPane.add(crowdImagePanel);
        contentPane.add(personNumTextLabel);
        contentPane.add(optErrorTextLabel);

        contentPane.add(segmentTextInput);
        contentPane.add(segmentTextInputLabel);
        contentPane.add(thresholdTextInput);
        contentPane.add(thresholdTextInputLabel);

    }

    private void startAction() {
        Util.logger(Level.INFO, "Start");
        if (pythonScriptTask.getCmdList().size() < 5) {
            if (pythonScriptTask.getCmdList().size() < 4) {
                showWarningText("以默认参数启动");
            } else {
                showWarningText("请输入必要参数，按回车确认");
                return;
            }
            Util.logger(Level.WARNING, "Please set input parameters, cmdList = " + pythonScriptTask.getCmdList());
        }
        if (new File(END_FLAG_FILE).exists() && !new File(END_FLAG_FILE).delete()) {
            Util.logger(Level.WARNING, "Failed to remove the END FLAG file");
            return;
        }
        if (new File(STOP_FLAG_FILE).exists() && !new File(STOP_FLAG_FILE).delete()) {
            Util.logger(Level.WARNING, "Failed to remove the STOP FLAG file");
            return;
        }
        switch (showLabelThreadState) {
            case CLOSE:
                start();//初始启动
                break;
            case STOP:
                showLabelThreadState = START;//暂停后启动
                break;
        }
    }

    private void closeAction() {
        if (showLabelThreadState == CLOSE) return;
        showLabelThreadState = CLOSE;
        Util.logger(Level.INFO, "Press to close");
        clearPythonScriptInput();
        if (!Util.createFile(END_FLAG_FILE)) {
            System.out.println("python脚本结束标志文件创建失败");
        }
        pythonScriptTask.endPythonScript();
    }

    private void stopAction() {
        if (showLabelThreadState == CLOSE) return;
        showLabelThreadState = STOP;
        Util.logger(Level.INFO, "Press to stop");
        if (!Util.createFile(STOP_FLAG_FILE)) {
            System.out.println("python脚本暂停标志文件创建失败");
        }
    }

    private void segmentTextInputAction() {
        if (cmdTextInput(segmentTextInput, segmentTextInputFlag)) {
            segmentTextInputFlag = true;
            segmentTextInput.setForeground(Color.GRAY);
        }
    }

    private void thresholdTextInputAction() {
        if (!segmentTextInputFlag) {
            showWarningText("请按顺序录入");
            return;
        }
        if (cmdTextInput(thresholdTextInput, thresholdTextInputFlag)) {
            thresholdTextInputFlag = true;
            thresholdTextInput.setForeground(Color.GRAY);
        }
    }


    public boolean checkTextInput(String input) {
        if (CrowdCountingShow.showLabelThreadState != CLOSE) {
            showWarningText("应用正在运行中，无法设置参数：" + input);
            Util.logger(Level.INFO, "The application is already started, so you can't set it");
            return false;
        }
        if (!Util.isNumeric(input)) {
            showWarningText("输入参数类型错误：" + input);
            Util.logger(Level.INFO, "The type of input is wrong");
            return false;
        }
        Util.logger(Level.INFO, "User enter:" + input);
        return true;
    }

    public void showWarningText(String warningText) {
        optErrorTextLabel.setText(warningText);
        optErrorTextLabel.setVisible(true);
        Timer warningTimer = new Timer(2000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                optErrorTextLabel.setVisible(false);
            }
        });
        warningTimer.setRepeats(false);
        warningTimer.start();
    }

    private void clearPythonScriptInput() {
        ArrayList<String> cmdList = pythonScriptTask.getCmdList();
        while (cmdList.size() >= 4) {
            cmdList.remove(cmdList.size() - 1);
        }
        segmentTextInputFlag = false;
        segmentTextInput.setForeground(Color.BLACK);
        thresholdTextInputFlag = false;
        thresholdTextInput.setForeground(Color.BLACK);
    }

    private boolean cmdTextInput(JTextField textInput, Boolean textInputFlag) {
        String input = textInput.getText();
        if (textInputFlag) {
            showWarningText("参数已录入，请勿重复操作");
            return false;
        }
        if (!checkTextInput(input)) return false;
        pythonScriptTask.addInputValueToCmd(input);
        return true;
    }

    public void showCrowdCounting() {
        addFrameComponents();
        crowdCountingDisplayFrame.setVisible(true);
    }

}
